/**
 * 对请求的数据进行缓存
 */
import { ReqResponse } from '@/shims';
import { isBoolean } from 'lodash';
import { App } from 'vue';

export default class Cacher {
  private static cacher?: Cacher;
  private cacheObj: Map<string, any>;//数据容器
  private capacity: number = -1;//缓存数量
  private capacityArr: string[];//api 容器
  static instance = this.getInstance();// 获取缓存实例

  //设置私有构造 达到禁止new的目的
  private constructor() {
    this.cacheObj = new Map();
    this.capacityArr = []
  }
  private static getInstance() {
    if (!this.cacher) {
      this.cacher = new Cacher();
    }
    return this.cacher
  }
  /**
   * 设置最多存储多少个数据  超出会将一个数据删除
   * @param num capacity size
   */
  setCapacity(num: number) {
    console.log('设置缓存数量----：', num)
    this.capacity = num
  }
  /**
   * 存储数据
   * @param api data key
   * @param data  data
   * @returns 是否成功
   */
  private set(api: string, data: any): Boolean {
    this.cacheObj.set(api, data);
    return true
  }
  /**
   * 根据api去缓存中查找数据 如果没有就去请求数据
   * @param api is request url
   * @returns axios responese
   */
  private get(api: string): any {
    if (this.cacheObj.has(api)) {
      this.capacity < this.capacityArr.length && this.shift(api)
      return this.cacheObj.get(api)
    } else {
      return false
    }
  }
  /**
   * 将前的api移到最后，防止超出容量被删除
   * @param api 
   */
  private shift(api: string) {
    const _index = this.capacityArr.indexOf(api)
    const _del = this.capacityArr.splice(_index, 1)[0];
    this.capacityArr.push(_del)
  }

  /**
   * 根据api去删除缓存中的数据
   * @param api 
   * @returns 
   */
  remove(api: string): Boolean {
    return this.cacheObj.delete(api)
  }
  /**
   * 超出容量删除第一个数据
   * @param api data key
   */
  private handle(api: string) {
    this.capacityArr.push(api);
    if (this.capacity && this.capacityArr.length > this.capacity) {
      const _d = this.capacityArr.shift();
      _d && this.remove(_d)
    }
  }
  /**
   * 获取数据
   * @param call axios 回调函数
   * @returns 
   */
  getData(call: (res: any) => Promise<ReqResponse.Result<ReqResponse.Data>>) {
    return (api: string, params: {}) => {
      const _this = this;
      return new Promise((resolve, reject) => {
        //获取缓存中的值 如果没有就去请求
        let data = _this.get(api);
        if (isBoolean(data)) {
          console.log('请求后端---222---')
          call(params).then(res => {
            _this.set(api, res);
            _this.handle(api)
            resolve(res);
          }).catch(err => {
            reject(err)
          });
        } else {
          console.log('在前端缓存中得到的数据---111---')
          resolve(data);
        }
      });
    };
  }
}
export const Cache = {
  install: function (app: App, capacity?: number) {
    capacity && capacity > 1 && Cacher.instance.setCapacity(capacity)
  }
}
